/*
 * CmdOption.h
 *
 *  Created on: Nov 8, 2010
 *      Author: Chengnian Sun
 */

#ifndef CMDOPTION_H_
#define CMDOPTION_H_

#include <boost/program_options.hpp>

#include "../detection-model/IndexingType.h"
#include "../feature-vector-calculator/FeatureVectorCalculatorFactory.h"
#include "../plain-similarity-measures/PlainSimilarityMeasureFactory.h"
#include "../detector/DetectorFactory.h"
#include "MacroUtility.h"

namespace po = boost::program_options;
using namespace std;

#include <string>
#include <iostream>

/**
 * this is only for releasing to public.
 */
#define ONLY_ENABLE_RANKNET

class CmdOption {
private:

  unsigned m_training_duplicates;

  int m_iteration;

  int m_top_k;

  double m_limit_k;


  int trainingStartID;
  int trainingEndID;
  //	int m_feature_calculator_type;
  FeatureVectorCalculatorFactory::EnumFeatureCalculatorType m_feature_calculator_type;

  PlainSimilarityMeasureFactory::SimilarityMeasureType m_plain_measure_type;

  string m_dataset;

  string m_project_name;

  string m_parsing_error;

  string m_recommendation_file;

  DetectorFactory::EnumDetectorType m_detector_type;

  string m_ranknet_config_file;

  po::variables_map m_variable_map;

  po::options_description m_visible_options;

  bool m_evolve_model;

  bool m_detect_all_reports;

  IndexingType::EnumIndexingType m_indexing_type;

  string m_validation_error;

public:

  static unsigned numberOfTrainingConfigMax;
  static double startTestingLimitID;
  static int startTrainingID;
  static int endTrainingID;


  unsigned number_of_training_duplicates() const {
    return this->m_training_duplicates;
  }

  IndexingType::EnumIndexingType indexing_type() const {
    return this->m_indexing_type;
  }

  int get_top_k() const {
    return this->m_top_k;
  }


  int get_trainingStartId() const;
  int get_trainingEndId() const;

  double get_limit_k() const;

  string get_ranknet_config_file() const {
    if (!this->is_using_ranknet_detector()) {
      fprintf(stderr,
          "the detector type is not RankNetDetector, cannot retrieve ranknet config file.");
      exit(EXIT_FAILURE);
    } else {
      return this->m_ranknet_config_file;
    }
  }

  bool detecting_all_reports() const {
    return this->m_detect_all_reports;
  }

  string get_recommendation_file() const {
    return this->m_recommendation_file;
  }

  PlainSimilarityMeasureFactory::SimilarityMeasureType get_plain_similarity_type() const {
    return this->m_plain_measure_type;
  }

  DetectorFactory::EnumDetectorType get_detector_type() const {
    return this->m_detector_type;
  }
  bool is_using_ranknet_detector() const {
    return this->m_detector_type == DetectorFactory::RANK_NET;
  }

  bool is_using_plain_detector() const {
    return this->m_detector_type == DetectorFactory::PLAIN;
  }

  bool is_using_svm_detector() const {
    return this->m_detector_type == DetectorFactory::SVM;
  }

  bool is_to_evolve_model() const {
    return this->m_evolve_model;
  }

  int get_iteration() const {
    return this->m_iteration;
  }

  FeatureVectorCalculatorFactory::EnumFeatureCalculatorType get_feature_calculator_type() const {
    return this->m_feature_calculator_type;
  }

  const string& get_project_name() const {
    return this->m_project_name;
  }

  const string& get_dataset_path() const {
    return this->m_dataset;
  }

  bool has_parsing_error() const {
    return !(this->m_parsing_error.empty());
  }

  void print_parsing_error() const {
    cout << this->m_parsing_error << '\n';
  }

  bool has_help() const;

  void print_help() const;

  bool has_version() const;

  void print_version() const {
    cout << "Version 0.1 \nBuilt on (" << __TIME__ << ", " << __DATE__ << ")\n";
  }

  void validate_options();

  bool has_validation_error() const {
    return !(this->m_validation_error.empty());
  }

  void print_validation_error() const {
    cout << this->m_validation_error << '\n';
  }

  CmdOption(int argc, char *argv[]);

  ~CmdOption();
};

#endif /* CMDOPTION_H_ */
